﻿using mozhi.smarterp.AuthorCenter.Permissions;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp;
using Volo.Abp.Guids;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using mozhi.smarterp.AuthorCenter.Enums;

namespace mozhi.smarterp.AuthorCenter.Idenities
{
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(CustomerIdentityDataSeedContributor), typeof(IdentityDataSeedContributor), typeof(IDataSeedContributor))]
    public class CustomerIdentityDataSeedContributor : IdentityDataSeedContributor
    {
        protected IGuidGenerator GuidGenerator { get; }
        protected IIdentityRoleRepository RoleRepository { get; }
        protected IIdentityUserRepository UserRepository { get; }
        protected ILookupNormalizer LookupNormalizer { get; }
        protected IdentityUserManager UserManager { get; }
        protected IdentityRoleManager RoleManager { get; }
        protected ICurrentTenant CurrentTenant { get; }
        protected IOptions<IdentityOptions> IdentityOptions { get; }

        public CustomerIdentityDataSeedContributor(IIdentityDataSeeder identityDataSeeder , IGuidGenerator guidGenerator,
        IIdentityRoleRepository roleRepository,
        IIdentityUserRepository userRepository,
        ILookupNormalizer lookupNormalizer,
        IdentityUserManager userManager,
        IdentityRoleManager roleManager,
        ICurrentTenant currentTenant,
        IOptions<IdentityOptions> identityOptions) : base(identityDataSeeder)
        {
            GuidGenerator = guidGenerator;
            RoleRepository = roleRepository;
            UserRepository = userRepository;
            LookupNormalizer = lookupNormalizer;
            UserManager = userManager;
            RoleManager = roleManager;
            CurrentTenant = currentTenant;
            IdentityOptions = identityOptions;
        }

        public override async Task SeedAsync(DataSeedContext context)
        {
            var adminEmail = context?[AdminEmailPropertyName] as string ?? "admin@mozhi.com.cn";
            var adminPassword = context?[AdminPasswordPropertyName] as string ?? AdminPasswordDefaultValue;

            Check.NotNullOrWhiteSpace(adminEmail, nameof(adminEmail));
            Check.NotNullOrWhiteSpace(adminPassword, nameof(adminPassword));

            if (context == null || context.TenantId.HasValue)
                return;

            await IdentityOptions.SetAsync();

            var result = new IdentityDataSeedResult();
            //"admin" user
            const string adminUserName = "admin";
            var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
                LookupNormalizer.NormalizeName(adminUserName)
            );

            if (adminUser != null)
                return;

            adminUser = new IdentityUser(GuidGenerator.Create(), adminUserName, adminEmail, null)
            {
                Name = adminUserName
            };

            adminUser.ExtraProperties.Add("UserType", UserType.PlatformAdmin);

            (await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors();
            result.CreatedAdminUser = true;

            //"admin" role
            const string adminRoleName = "admin";
            var adminRole =
                await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName(adminRoleName));
            if (adminRole == null)
            {
                adminRole = new IdentityRole(
                    GuidGenerator.Create(),
                    adminRoleName,
                    null
                )
                {
                    IsStatic = true,
                    IsPublic = true
                };
                adminRole.ExtraProperties.Add("RoleType", RoleType.PlatformRole);

                (await RoleManager.CreateAsync(adminRole)).CheckErrors();
                result.CreatedAdminRole = true;
            }

                (await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();

        }
    }
}
